home *** CD-ROM | disk | FTP | other *** search
-
- #include <ctype.h>
- #include <errno.h>
- #include <math.h>
- #include "float.h"
- #ifndef errno
- extern int errno;
- #endif
- extern struct {
- double n[308];
- double p[DBL_MAX_10_EXP + 1];
- } dp10_;
-
-
- double atof(dstr)
- char *dstr; /* any correctly working atof() may be used */
- {
- int c, /* difference from exponent of accumulated
- integer to final value */
- exp = 0, neg_val = 0, /* leading negative sign ? */
- e_exp = 0, /* number after e/E +/- */
- neg_exp = 0, /* - after E/e ? */
- fdig = 0;
- #ifdef __STDC__
- long double x, retval = 0, r = 0;
- #else
- register double x, retval = 0, r = 0;
- #endif
- while (isspace(c = *dstr)) /* skip leading space */
- dstr++;
- switch (c) { /* optional sign */
- case '-':
- neg_val = 1;
- case '+': /* fall-through */
- dstr++;
- }
-
- if (isdigit(c = *dstr++))
- /* add up converted values before dec point */
- do /* changed from while to do while for optimization */
- retval = 10 * retval + (double) (c - '0' while (isdigit(c = *dstr++));
- if (c == '.')
- #if LDBL_DIG > DBL_DIG
- while (isdigit(c = *dstr++)) /* and after dec pt */
- retval += (c - '0') * dp10_.p[--fdig];
- #else
- if (isdigit(c = *dstr++))
- for (;;) { /* and after dec pt, order of operations
- must be as shown */
- retval = (x = retval) + (r += (c - '0') * dp10_.p[--fdig]);
- if (!isdigit(c = *dstr++))
- break;
- r += x -= retval; /* numerical error correction term */
- }
- #endif
- if ((c | ' ') == 'e') { /* found an exponent lead-in */
-
- switch (*dstr) { /* sign field */
- case '-':
- neg_exp = 1;
- case '+': /* fall-through */
- case ' ': /* many FORTRAN environments generate this! */
- dstr++;
- default:
- ; /* fall-through */
- }
- if (isdigit(c = *dstr)) /* found exponent digit */
- do
- e_exp = 10 * e_exp + (int) (c - '0');
- while (isdigit(c = *++dstr));
- }
- if ((exp += neg_exp ? -e_exp : e_exp) >= 0)
- if (exp <= DBL_MAX_10_EXP)
- retval *= dp10_.p[exp];
- else {
- errno = ERANGE;
- retval = HUGE_VAL;
- }
- else if ((exp = -exp) <= DBL_MAX_10_EXP)
- retval /= dp10_.p[exp];
- else if (exp - DBL_MAX_10_EXP / 2 <= DBL_MAX_10_EXP) {
- retval /= dp10_.p[DBL_MAX_10_EXP / 2];
- retval /= dp10_.p[exp - DBL_MAX_10_EXP / 2];
- } else {
- retval = 0;
- errno = ERANGE;
- }
- return (neg_val ? -retval : retval); /* apply sign */
- }
-